package com.omnisyr.textrebuilder.common;

import java.util.Comparator;

import com.omnisyr.textrebuilder.util.Sorted;
import com.omnisyr.textrebuilder.util.structure.SimpleArrayList;

public class Color implements ICoord3Dable {

	private int red;
	private int green;
	private int blue;
	private int color;

	public Color(int color) {

		this.blue = color & 0xff;
		this.green = (color & 0xff00) >> 8;
		this.red = (color & 0xff0000) >> 16;

		this.color = color;

	}

	public Color(int red, int green, int blue) {

		this.blue = blue;
		this.green = green;
		this.red = red;

		this.color = this.blue | (this.green << 8) | (this.red << 16);

	}

	@Override
	public int hashCode() {

		return this.color;

	}

	public boolean isGray() {

		return getLoss(this, new Color(this.red, this.red, this.red)) <= 5
				|| getLoss(this, new Color(this.green, this.green, this.green)) <= 5
				|| getLoss(this, new Color(this.blue, this.blue, this.blue)) <= 5;

	}

	public boolean isInBlackList(@Sorted SimpleArrayList<Color> blackList) {

		return blackList.search(this, hashComparator) >= 0;

	}

	@Override
	public String toString() {

		return this.red + " " + this.green + " " + this.blue;

	}

	public int toInteger() {

		return this.blue | (this.green << 8) | (this.red << 16);

	}

	/**
	 * 
	 * @param index</BR>
	 *                   0: R</BR>
	 *                   1: G</BR>
	 *                   2: B</BR>
	 * @return
	 */
	public int toSingle(int index) {

		if (index == 0) {

			return this.red;

		}

		if (index == 1) {

			return this.green;

		}

		return this.blue;

	}

	@Override
	public boolean equals(Object color) {

		if (!(color instanceof Color)) {

			return false;

		}

		return this.color == ((Color) color).color;

	}

	public String toFileString() {

		return String.valueOf(this.color);

	}

	public static Color ofString(String str) {

		return new Color(Integer.parseInt(str));

	}

	public static Comparator<Color> hashComparator = (a, b) -> Integer.compare(a.hashCode(), b.hashCode());
	public static Comparator<Color> rgbComparator = Color::rgbCompare;

	public static int getLoss(Color a, Color b) {

		int loss = 0;

		int[] weight = new int[] { 1, 1, 1 };

		loss += (a.red - b.red) * (a.red - b.red) * weight[0];
		loss += (a.green - b.green) * (a.green - b.green) * weight[1];
		loss += (a.blue - b.blue) * (a.blue - b.blue) * weight[2];

		return (int) Math.pow(loss, 1.0 / 3);

	}

	private static int rgbCompare(Color a, Color b) {

		if (a.red != b.red) {

			return Integer.compare(a.red, b.red);

		}

		if (a.green != b.green) {

			return Integer.compare(a.green, b.green);

		}

		return Integer.compare(a.blue, b.blue);

	}

	@Override
	public Coord3D getCoord() {

		return new Coord3D(this.red, this.green, this.blue);

	}

}
